package com.eugenes.design;

import com.eugenes.design.cardvalidator.CardValidator;

/**
 * Thinking about SimpleCard.
 *
 * Why CardValidator is a part of SimpleCard? I am not
 * sure whether this is right approach but it just works and
 * I think that it is more flexible than some other ways to
 * define SimpleCard.
 *
 * Maybe, it is much better to think about CardValidator like
 * a part of checkpoint that can determine if card have valid
 * permissions to pass it. So data needed for this validation
 * should be placed somewhere in card. However, in this implementation
 * behavior is also part (part ~= reference to validation system
 * inside system itself) of it.
 *
 * For example reason why card is allowed or disallowed to
 * pass checkpoint have to be internal checkpoint information.
 * But it can be implemented as passing some information-object to
 * validator and it can append its own comment to info-object.
 *
 * !!! Another approach should be considered. Card contains id only.
 * System has validators for all cards. After mapping card to validator
 * system can provide result for checkpoint. !!!
 *
 * !!! Create code (hash secret word with card id) for card which can
 * provide proof that card is truly created by system. Also can change
 * it after each pass so that user cannot copy it (hash(current code) ?) !!!
 *
 * @author Yevhen_Shevchuk
 */
public class SimpleCard implements Card {

    final long id;

    CardValidator validator = new CardValidator() {

        @Override
        public boolean validate(Card card) {
            return true;
        }

        @Override
        public void cardIsUsed(Card card) {}
    };

    SimpleCard(long id) {
        this.id = id;
    }

    SimpleCard(long id, CardValidator validator) {
        this(id);

        if (validator == null) {
            throw new IllegalArgumentException("Validator is null.");
        }

        this.validator = validator;
    }

    @Override
    public boolean use() {
        if (!canUse()) {
            return false;
        }

        validator.cardIsUsed(this);
        return true;
    }

    @Override
    public boolean canUse() {
        return validator.validate(this);
    }
}
